{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"https://raw.githubusercontent.com/Qiskit/qiskit-tutorials/master/images/qiskit-heading.png\" alt=\"Note: In order for images to show up in this jupyter notebook you need to select File => Trusted Notebook\" width=\"500 px\" align=\"left\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tutorial: The Structure of the Clifford Group\n",
    "\n",
    "### Contributors\n",
    "\n",
    "Shelly Garion$^1$ and Gadi Aleksandrowicz$^1$\n",
    "\n",
    "1. IBM Research Haifa, Haifa University Campus, Mount Carmel Haifa, Israel\n",
    "\n",
    "### Qiskit Package Versions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'qiskit': '0.10.3',\n",
       " 'qiskit-terra': '0.8.1',\n",
       " 'qiskit-ignis': '0.1.1',\n",
       " 'qiskit-aer': '0.2.1',\n",
       " 'qiskit-ibmq-provider': '0.2.2',\n",
       " 'qiskit-aqua': '0.5.1'}"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import qiskit\n",
    "qiskit.__qiskit_version__"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Introduction \n",
    "\n",
    "The goal of this notebook is to describe the structure of the **Clifford group**. This group consists of the quantum operators that can be efficiently simulated (in polynomial time) using a classical computer, via a **Clifford simulator** (see [1]). \n",
    "In addition, the Clifford group is used for **Randomized Benchmarking**.\n",
    "\n",
    "## Definiton\n",
    "\n",
    "The **Pauli group** $P_n$ on $n$-qubits is generated by the $n$-fold tensor products of the **Pauli matrices** $\\{I,X,Y,Z\\}$:\n",
    "\n",
    "$$I=\\left(\\begin{array}{cc}\n",
    "1 & 0\\\\\n",
    "0 & 1\n",
    "\\end{array}\\right),X=\\left(\\begin{array}{cc}\n",
    "0 & 1\\\\\n",
    "1 & 0\n",
    "\\end{array}\\right),Y=\\left(\\begin{array}{cc}\n",
    "0 & -i\\\\\n",
    "i & 0\n",
    "\\end{array}\\right),Z=\\left(\\begin{array}{cc}\n",
    "1 & 0\\\\\n",
    "0 & -1\n",
    "\\end{array}\\right)$$\n",
    "\n",
    "We denote $A \\equiv B$ if $A = \\lambda B$ for some $\\lambda \\in \\mathbb{C}$, and define $U(1) = \\{\\lambda I_n: \\lambda \\in \\mathbb{C} \\} \\cong \\mathbb{C}$. Under this equivalence relation (i.e., neglecting the global phase), we have the following relations betweeen the Pauli matrices:\n",
    "\n",
    "$$XY\\equiv YX \\equiv Z$$\n",
    "$$YZ\\equiv ZY \\equiv X$$\n",
    "$$ZX\\equiv XZ \\equiv Y$$\n",
    "$$X^{2}=Y^{2}=Z^{2}=I$$\n",
    "\n",
    "so the group $\\{I,X,Y,Z\\}$ is isomorphic to the Klein four-group $\\mathbb{F}_2^2$ and in general we have the group isomorphism $P_n/U(1) \\cong \\mathbb{F}_2^{2n}$.\n",
    "\n",
    "The **Clifford group** $C_n$ on $n$-qubits is defined as the normalizer of the Pauli group $P_n$, when neglecting the global phase $U(1) \\cong \\mathbb{C}$ (see [2]).\n",
    "\n",
    "It turns out that $C_n/P_n \\cong Sp(2n)$, where $Sp(2n)$ denotes the group of $2n \\times 2n$ **symplectic matrices** over the field $\\mathbb{F}_2$, which is *simple* for $n>2$ (see [3]). We recall that the symplectic group $Sp(2n)$ is the group of $2n \\times 2n$ matrices $S$ with entries in the field $\\mathbb{F}_2$ such that $S \\Lambda (n) S^{T} = \\Lambda (n)$ where $\\Lambda (n) = \\oplus_{i=1}^n$  $\\begin{pmatrix} 0 & 1 \\\\ 1 & 0\\end{pmatrix}$.\n",
    "\n",
    "We explicitly describe below the structure and elements in 1-qubit Clifford group $C_1$ and the 2-qubit Cliffod group $C_2$.\n",
    "\n",
    "### References\n",
    "\n",
    "[1] Scott Aaaronson and Daniel Gottesman, Improved Simulation of Stabilizer Circuits, https://arxiv.org/abs/quant-ph/0406196\n",
    "\n",
    "[2] Maris Ozlos, Clifford group, 2008,\n",
    "http://home.lu.lv/~sd20008/papers/essays/Clifford%20group%20[paper].pdf \n",
    "\n",
    "[3] Robert Koenig and John Smolin, How to efficiently select an arbitrary Clifford group element, https://arxiv.org/abs/1406.2170\n",
    "\n",
    "[4] A. D. C'orcoles, Jay M. Gambetta, Jerry M. Chow, John A. Smolin, Matthew Ware, J. D. Strand, B. L. T. Plourde, and M. Steffen, Supplementary material for ''Process verification of two-qubit quantum gates by randomized benchmarking'', https://arxiv.org/pdf/1210.7011.pdf "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "\n",
    "import matplotlib\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import sympy\n",
    "from sympy import *\n",
    "import itertools\n",
    "from IPython.display import display\n",
    "init_printing() #allows nice math displays"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Quantum matrix class\n",
    "\n",
    "We use the following class to explicitly present a quantum matrix in the Clifford group $C_1$ up to a global phase (coefficient)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class QuantumMatrix():\n",
    "    def __init__(self, m, coeff = 1):\n",
    "        self.matrix = sympy.Matrix(m)\n",
    "        self.coefficient = coeff\n",
    "        self.canonize()\n",
    "        \n",
    "    def canonize(self):\n",
    "        a = next((x for x in self.matrix if x != 0), None)\n",
    "        if a is not None: #zero vector\n",
    "            for i,j in itertools.product([0,1], [0,1]):\n",
    "                self.matrix[i,j] = sympy.simplify(self.matrix[i,j] / a)\n",
    "        self.coefficient = sympy.simplify(self.coefficient * a) \n",
    "            \n",
    "    def __str__(self):\n",
    "        coeff_string = \"\"\n",
    "        if self.coefficient != 1:\n",
    "            coeff_string = \"{} * \".format(self.coefficient)\n",
    "        return \"{}[[{}, {}], [{}, {}]]\".format(coeff_string,self.matrix[0], self.matrix[1], self.matrix[2], self.matrix[3])\n",
    "    \n",
    "    def __mul__(self, rhs):\n",
    "        return QuantumMatrix(self.matrix * rhs.matrix, self.coefficient * rhs.coefficient)\n",
    "    \n",
    "    def __add__(self, rhs):\n",
    "        temp_rhs_matrix = sympy.Matrix([[1,0],[0,1]])\n",
    "        for i,j in itertools.product([0,1], [0,1]):\n",
    "                 temp_rhs_matrix[i,j] = sympy.simplify((rhs.matrix[i,j] * self.coefficient) / rhs.coefficient)\n",
    "        return QuantumMatrix(self.matrix + temp_rhs_matrix, self.coefficient * 1/sympy.sqrt(2))\n",
    "    \n",
    "    def __sub__(self, rhs):\n",
    "        return self + QuantumMatrix(rhs.matrix, rhs.coefficient * -1)\n",
    "    \n",
    "    def __eq__(self, rhs):\n",
    "        return (self.matrix == rhs.matrix and self.coefficient == rhs.coefficient)\n",
    "    \n",
    "    def equiv(self, rhs):\n",
    "        return (self.matrix == rhs.matrix)\n",
    "    \n",
    "    def __iter__(self):\n",
    "        for x in self.matrix:\n",
    "             yield x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The Clifford group on 1 qubit\n",
    "\n",
    "The **Pauli group** $P_1$ is generated by the Pauli matrices $\\{I,X,Y,Z\\}$. When neglecting the global phase $U(1) \\cong \\mathbb{C}$ we get that $P_1/U(1) \\cong \\mathbb{F}_2^2$. \n",
    "\n",
    "The **Clifford group** $C_1$ on 1-qubit is defined as the normalizer of the Pauli group $P_1$ (when neglecting the global phase $U(1) \\cong \\mathbb{C}$).\n",
    "\n",
    "It turns out that $C_1/P_1 \\cong Sp(2) \\cong SL(2,2) \\cong S_3$, where $Sp(2)$ and $SL(2,2)$ denote the $2 \\times 2$ symplectic matrices and the $2 \\times 2$ matrices of determinant 1 over the field with 2 elements, respectively, and $S_3$ is the symmetric group on 3 elements. Indeed, one can explicitly verify that \n",
    "\n",
    "$$Sp(2) \\cong SL(2,2) = \\left\\{ \\begin{pmatrix} 1 & 0 \\\\ 0 & 1\\end{pmatrix} , \n",
    "\\begin{pmatrix} 0 & 1 \\\\ 1 & 0\\end{pmatrix} , \\begin{pmatrix} 1 & 1 \\\\ 0 & 1\\end{pmatrix} ,\n",
    "\\begin{pmatrix} 1 & 0 \\\\ 1 & 1\\end{pmatrix} , \\begin{pmatrix} 0 & 1 \\\\ 1 & 1\\end{pmatrix} ,\n",
    "\\begin{pmatrix} 1 & 1 \\\\ 1 & 0\\end{pmatrix} \\right\\} \\cong S_3$$\n",
    "\n",
    "We can think of $C_1$ as rotations of the Bloch sphere that permutes $\\pm x, \\pm y, \\pm z$ directions. There are 6 possibilities where the $x$ axis can go. Once we have fixed the $x$ axis, we can still rotate around it and thus there are 4 possibilities where the $z$ axis can go. Thus $C_1$ corresponds to the group $S_4$ of rotational symmetries of the cube (of order 24).\n",
    "\n",
    "We will explicitly show these statements below."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Pauli gates"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The Pauli matrices (when neglecting the global phase):\n",
      "Identity: I=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABOElEQVQ4EWMQFBRkwAIYBQUFGPT/f8YixcD1//8CBhVsMiAxViLkkgRAKuHgzOQLMH2Mxf0ochwPGHVhcgwM81HkghgYTuGSW87A8F6AgRXqFlR9QE/5P8AuxwiSC8Aux/uHgSF/Ah65A9jlGIH6/HHoYwDa9x6HWxhWMTDE4/JDNAODBS6/Mz1g3AaXq9qvPoEBARhPTk+AyyGEkVisRMQfknI4c4To4zlpC/cyiMGmCCRYIWHWxyAETMhwIG7xEchmBcuxKjDwLADy4IATIcdVwMAH4sEBkhy/AQPLP7gEkIEkJw+U+4pD7v4BBrafeOSAaRIBkM08wMCCSx/QLXy43MK1gIEVlx9YNzAwNyBsQ/EDgx6DdAIuOZmZZchS7Ks/VcLCE1kcwWYdXGlXFVfZKrkAX9kKAIdJdTXUNN/CAAAAAElFTkSuQmCC\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & 1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0⎤\n",
       "⎢    ⎥\n",
       "⎣0  1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "X=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGaJdiLNVLurMu++UplCAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABJ0lEQVQ4EWMQFBRkwAIYBQUFGPT/f8YixcD9//8GBhVsMiAxVsJybOkWKLp5FRH6ZjEINSBJylh+hMuxKjCwbUCSY2BHyHEfYOAC8eAASY7fgIHlF1wCyECSkwfKfcUh15/AwPsdj9w3HHLyCQwsuPQB3cKFyy3cGxhYcfmB9QED8wQc9jFoMchdwCUnVn4WWYpn36fjRMURsiY4m4i4hatFZgwnfZcEkH3GkFbcAAtPxsPzUeQ4FzBqwOQYGOpR5IIYGLJxye1hYFgvAM9HqPqAGdJ/AXY5RpBcAHY5DmBavV+ARy4BuxwjUJ8/Dn0MQPvW43ALw24GhnhcfohjYLDE5XemBYxv4XKn3+sUIAU2Y3rNBbgckjiCOcjSmSquslV8A76yFQDlSHUUUuAZNAAAAABJRU5ErkJggg==\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}0 & 1\\\\1 & 0\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡0  1⎤\n",
       "⎢    ⎥\n",
       "⎣1  0⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Y=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGaJdiLNVLurMu++UplCAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABPUlEQVQ4EWMQFBRkwAdA8vr/P+NTwrD//28GFbwqQJLRJKlhS7fAMJFXEdWcWQxCDWiKZCw/oqhhVWBg24CmhoEdVQ33AQYusAiyOjQ1/AYMLL+Q5UFsNDXyQDVfCajpT2Dg/U6Emm8E1MgnMLAQMgfoZi5CbubewMBKyO+sDxiYJxBwD4MWg9wFQmrEys+iK+HZ9+k4UIy0tIFuCII/ag4iLLCxyAifSwIoBqUVNwD5KOYwHp6PooZzAaMGuhoGhnoUNUEMDNmE1OxhYFgP1IRiF7o5wILJfwF+NYwgNQH41XAA89v9AiLUJEDVME5SAoELaO5hBJrjT8AcBqB71hNwM8NuBoZ4AfzuYYhjYLAkFIZMCxjfYqg5/V4H6EY4YEyvAfoDPZzh0sgMtLhAloKzB58aVYJ1XDUxdRwA7L5mXz5GEq8AAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}0 & 1\\\\-1 & 0\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡0   1⎤\n",
       "⎢     ⎥\n",
       "⎣-1  0⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Z=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABQ0lEQVQ4EWMQFBRkwAdA8vr/P+NTwrD+/y8GFbwqQJJRxKtJEsAw7czkC1AxsDmMxf0YajgeMOoiq2FgmI+hJoiB4RQhNcsZGN5DNULdjGkOMED8H0AMwqWGEaQmAL8a3j8MDPkTiFBzAL8aRqA5/gTMYQC65/0D/OYwrGJgiCfk92gGBguIMbA4xQwfpgeM21DUVO1Xh7oPKszAwHhyegKKGrgMVgYJ6QerfpjgqDmwkMBOQ8KH56QtVmk2RZAwRE0fg9AFLIrELT7C1bAqMPAswKKGgROhhquAgQ/MQ1eHpIbfgIHlH7o8iI+kRh6o5isBNfcPMLD9JEINMD9hAmS7DjCwIJsjoQQCaijuAbqZj5CbuRYwsBLyO+sGBuYGTNeg2MWgxyCdQEiNzMwybErYV3+qBIoP33yhSrCOm0VMHQcAMdRoSULFp7cAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & -1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0 ⎤\n",
       "⎢     ⎥\n",
       "⎣0  -1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "X = QuantumMatrix( [[0,1],  [1,0]])\n",
    "Y = QuantumMatrix( [[0,-sympy.I], [sympy.I,0]])\n",
    "Z = QuantumMatrix( [[1,0],  [0,-1]])\n",
    "I = QuantumMatrix( [[1,0],  [0,1]])\n",
    "\n",
    "print (\"The Pauli matrices (when neglecting the global phase):\")\n",
    "print (\"Identity: I=\")\n",
    "display(sympy.Matrix(I.matrix))\n",
    "print (\"X=\")\n",
    "display(sympy.Matrix(X.matrix))\n",
    "print (\"Y=\")\n",
    "display(sympy.Matrix(Y.matrix))\n",
    "print (\"Z=\")\n",
    "display(sympy.Matrix(Z.matrix))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The Pauli gates X,Y,Z are of order 2:\n",
      "X*X=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABOElEQVQ4EWMQFBRkwAIYBQUFGPT/f8YixcD1//8CBhVsMiAxViLkkgRAKuHgzOQLMH2Mxf0ochwPGHVhcgwM81HkghgYTuGSW87A8F6AgRXqFlR9QE/5P8AuxwiSC8Aux/uHgSF/Ah65A9jlGIH6/HHoYwDa9x6HWxhWMTDE4/JDNAODBS6/Mz1g3AaXq9qvPoEBARhPTk+AyyGEkVisRMQfknI4c4To4zlpC/cyiMGmCCRYIWHWxyAETMhwIG7xEchmBcuxKjDwLADy4IATIcdVwMAH4sEBkhy/AQPLP7gEkIEkJw+U+4pD7v4BBrafeOSAaRIBkM08wMCCSx/QLXy43MK1gIEVlx9YNzAwNyBsQ/EDgx6DdAIuOZmZZchS7Ks/VcLCE1kcwWYdXGlXFVfZKrkAX9kKAIdJdTXUNN/CAAAAAElFTkSuQmCC\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & 1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0⎤\n",
       "⎢    ⎥\n",
       "⎣0  1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Y*Y=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABOElEQVQ4EWMQFBRkwAIYBQUFGPT/f8YixcD1//8CBhVsMiAxViLkkgRAKuHgzOQLMH2Mxf0ochwPGHVhcgwM81HkghgYTuGSW87A8F6AgRXqFlR9QE/5P8AuxwiSC8Aux/uHgSF/Ah65A9jlGIH6/HHoYwDa9x6HWxhWMTDE4/JDNAODBS6/Mz1g3AaXq9qvPoEBARhPTk+AyyGEkVisRMQfknI4c4To4zlpC/cyiMGmCCRYIWHWxyAETMhwIG7xEchmBcuxKjDwLADy4IATIcdVwMAH4sEBkhy/AQPLP7gEkIEkJw+U+4pD7v4BBrafeOSAaRIBkM08wMCCSx/QLXy43MK1gIEVlx9YNzAwNyBsQ/EDgx6DdAIuOZmZZchS7Ks/VcLCE1kcwWYdXGlXFVfZKrkAX9kKAIdJdTXUNN/CAAAAAElFTkSuQmCC\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & 1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0⎤\n",
       "⎢    ⎥\n",
       "⎣0  1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Z*Z=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABOElEQVQ4EWMQFBRkwAIYBQUFGPT/f8YixcD1//8CBhVsMiAxViLkkgRAKuHgzOQLMH2Mxf0ochwPGHVhcgwM81HkghgYTuGSW87A8F6AgRXqFlR9QE/5P8AuxwiSC8Aux/uHgSF/Ah65A9jlGIH6/HHoYwDa9x6HWxhWMTDE4/JDNAODBS6/Mz1g3AaXq9qvPoEBARhPTk+AyyGEkVisRMQfknI4c4To4zlpC/cyiMGmCCRYIWHWxyAETMhwIG7xEchmBcuxKjDwLADy4IATIcdVwMAH4sEBkhy/AQPLP7gEkIEkJw+U+4pD7v4BBrafeOSAaRIBkM08wMCCSx/QLXy43MK1gIEVlx9YNzAwNyBsQ/EDgx6DdAIuOZmZZchS7Ks/VcLCE1kcwWYdXGlXFVfZKrkAX9kKAIdJdTXUNN/CAAAAAElFTkSuQmCC\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & 1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0⎤\n",
       "⎢    ⎥\n",
       "⎣0  1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "print (\"The Pauli gates X,Y,Z are of order 2:\")\n",
    "A=X*X\n",
    "print (\"X*X=\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=Y*Y\n",
    "print (\"Y*Y=\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=Z*Z\n",
    "print (\"Z*Z=\")\n",
    "display(sympy.Matrix(A.matrix))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "For example, one can verify that X*Y=Y*X=Z:\n",
      "X*Y = Z =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABQ0lEQVQ4EWMQFBRkwAdA8vr/P+NTwrD+/y8GFbwqQJJRxKtJEsAw7czkC1AxsDmMxf0YajgeMOoiq2FgmI+hJoiB4RQhNcsZGN5DNULdjGkOMED8H0AMwqWGEaQmAL8a3j8MDPkTiFBzAL8aRqA5/gTMYQC65/0D/OYwrGJgiCfk92gGBguIMbA4xQwfpgeM21DUVO1Xh7oPKszAwHhyegKKGrgMVgYJ6QerfpjgqDmwkMBOQ8KH56QtVmk2RZAwRE0fg9AFLIrELT7C1bAqMPAswKKGgROhhquAgQ/MQ1eHpIbfgIHlH7o8iI+kRh6o5isBNfcPMLD9JEINMD9hAmS7DjCwIJsjoQQCaijuAbqZj5CbuRYwsBLyO+sGBuYGTNeg2MWgxyCdQEiNzMwybErYV3+qBIoP33yhSrCOm0VMHQcAMdRoSULFp7cAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & -1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0 ⎤\n",
       "⎢     ⎥\n",
       "⎣0  -1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Y*X = Z =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABQ0lEQVQ4EWMQFBRkwAdA8vr/P+NTwrD+/y8GFbwqQJJRxKtJEsAw7czkC1AxsDmMxf0YajgeMOoiq2FgmI+hJoiB4RQhNcsZGN5DNULdjGkOMED8H0AMwqWGEaQmAL8a3j8MDPkTiFBzAL8aRqA5/gTMYQC65/0D/OYwrGJgiCfk92gGBguIMbA4xQwfpgeM21DUVO1Xh7oPKszAwHhyegKKGrgMVgYJ6QerfpjgqDmwkMBOQ8KH56QtVmk2RZAwRE0fg9AFLIrELT7C1bAqMPAswKKGgROhhquAgQ/MQ1eHpIbfgIHlH7o8iI+kRh6o5isBNfcPMLD9JEINMD9hAmS7DjCwIJsjoQQCaijuAbqZj5CbuRYwsBLyO+sGBuYGTNeg2MWgxyCdQEiNzMwybErYV3+qBIoP33yhSrCOm0VMHQcAMdRoSULFp7cAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & -1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0 ⎤\n",
       "⎢     ⎥\n",
       "⎣0  -1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Similarly, X*Z=Z*X=Y, Y*Z=Z*Y=X\n"
     ]
    }
   ],
   "source": [
    "print (\"For example, one can verify that X*Y=Y*X=Z:\")\n",
    "A=X*Y\n",
    "B=Y*X\n",
    "print (\"X*Y = Z =\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "print (\"Y*X = Z =\")\n",
    "display(sympy.Matrix(B.matrix))\n",
    "print (\"Similarly, X*Z=Z*X=Y, Y*Z=Z*Y=X\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In conclusion, we obtain an isomorphism of groups: $P_1/U(1) \\cong \\mathbb{F}_2^2$."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We now discuss other elements in the Clifford group (when neglecting the global phase).\n",
    "\n",
    "### Hadamard gate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hadamard gate: H=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAJ1BMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAilU6eAAAADHRSTlMAEN2ZRGYyq812u+91lTu7AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAoUlEQVQ4EWMQFBRkwAdA8jpnDuNTwrDmzCkGFbwqQJJRxKtJEsAwjU0RJgQ2h7G4B0ONuMVBFDUMDHMw1DBwjqpBxAUdw6dqj/oEWOxAafbVhyqhTBLSBpohqNxRc1DDA51HQvhgyYMg0yD5EGceBCmB5kOoXVjSGEgRJB8OGzUSSiCgNrj9hSUPgqICmg9JSBsgXTjB4DNHlWAdN4uYOg4AYlROuMwACloAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 1\\\\1 & -1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  1 ⎤\n",
       "⎢     ⎥\n",
       "⎣1  -1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H is of order 2:\n",
      "H*H =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABOElEQVQ4EWMQFBRkwAIYBQUFGPT/f8YixcD1//8CBhVsMiAxViLkkgRAKuHgzOQLMH2Mxf0ochwPGHVhcgwM81HkghgYTuGSW87A8F6AgRXqFlR9QE/5P8AuxwiSC8Aux/uHgSF/Ah65A9jlGIH6/HHoYwDa9x6HWxhWMTDE4/JDNAODBS6/Mz1g3AaXq9qvPoEBARhPTk+AyyGEkVisRMQfknI4c4To4zlpC/cyiMGmCCRYIWHWxyAETMhwIG7xEchmBcuxKjDwLADy4IATIcdVwMAH4sEBkhy/AQPLP7gEkIEkJw+U+4pD7v4BBrafeOSAaRIBkM08wMCCSx/QLXy43MK1gIEVlx9YNzAwNyBsQ/EDgx6DdAIuOZmZZchS7Ks/VcLCE1kcwWYdXGlXFVfZKrkAX9kKAIdJdTXUNN/CAAAAAElFTkSuQmCC\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & 1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0⎤\n",
       "⎢    ⎥\n",
       "⎣0  1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H operates on the Pauli gates by conjugation as a reflection: X<-->Z:\n",
      "H*X*H = Z =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABQ0lEQVQ4EWMQFBRkwAdA8vr/P+NTwrD+/y8GFbwqQJJRxKtJEsAw7czkC1AxsDmMxf0YajgeMOoiq2FgmI+hJoiB4RQhNcsZGN5DNULdjGkOMED8H0AMwqWGEaQmAL8a3j8MDPkTiFBzAL8aRqA5/gTMYQC65/0D/OYwrGJgiCfk92gGBguIMbA4xQwfpgeM21DUVO1Xh7oPKszAwHhyegKKGrgMVgYJ6QerfpjgqDmwkMBOQ8KH56QtVmk2RZAwRE0fg9AFLIrELT7C1bAqMPAswKKGgROhhquAgQ/MQ1eHpIbfgIHlH7o8iI+kRh6o5isBNfcPMLD9JEINMD9hAmS7DjCwIJsjoQQCaijuAbqZj5CbuRYwsBLyO+sGBuYGTNeg2MWgxyCdQEiNzMwybErYV3+qBIoP33yhSrCOm0VMHQcAMdRoSULFp7cAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & -1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0 ⎤\n",
       "⎢     ⎥\n",
       "⎣0  -1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*Z*H = X =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGaJdiLNVLurMu++UplCAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABJ0lEQVQ4EWMQFBRkwAIYBQUFGPT/f8YixcD9//8GBhVsMiAxVsJybOkWKLp5FRH6ZjEINSBJylh+hMuxKjCwbUCSY2BHyHEfYOAC8eAASY7fgIHlF1wCyECSkwfKfcUh15/AwPsdj9w3HHLyCQwsuPQB3cKFyy3cGxhYcfmB9QED8wQc9jFoMchdwCUnVn4WWYpn36fjRMURsiY4m4i4hatFZgwnfZcEkH3GkFbcAAtPxsPzUeQ4FzBqwOQYGOpR5IIYGLJxye1hYFgvAM9HqPqAGdJ/AXY5RpBcAHY5DmBavV+ARy4BuxwjUJ8/Dn0MQPvW43ALw24GhnhcfohjYLDE5XemBYxv4XKn3+sUIAU2Y3rNBbgckjiCOcjSmSquslV8A76yFQDlSHUUUuAZNAAAAABJRU5ErkJggg==\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}0 & 1\\\\1 & 0\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡0  1⎤\n",
       "⎢    ⎥\n",
       "⎣1  0⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*Y*H = Y =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGaJdiLNVLurMu++UplCAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABPUlEQVQ4EWMQFBRkwAdA8vr/P+NTwrD//28GFbwqQJLRJKlhS7fAMJFXEdWcWQxCDWiKZCw/oqhhVWBg24CmhoEdVQ33AQYusAiyOjQ1/AYMLL+Q5UFsNDXyQDVfCajpT2Dg/U6Emm8E1MgnMLAQMgfoZi5CbubewMBKyO+sDxiYJxBwD4MWg9wFQmrEys+iK+HZ9+k4UIy0tIFuCII/ag4iLLCxyAifSwIoBqUVNwD5KOYwHp6PooZzAaMGuhoGhnoUNUEMDNmE1OxhYFgP1IRiF7o5wILJfwF+NYwgNQH41XAA89v9AiLUJEDVME5SAoELaO5hBJrjT8AcBqB71hNwM8NuBoZ4AfzuYYhjYLAkFIZMCxjfYqg5/V4H6EY4YEyvAfoDPZzh0sgMtLhAloKzB58aVYJ1XDUxdRwA7L5mXz5GEq8AAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}0 & 1\\\\-1 & 0\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡0   1⎤\n",
       "⎢     ⎥\n",
       "⎣-1  0⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "H = QuantumMatrix(  [[1,1],  [1,-1]], 1/sympy.sqrt(2))\n",
    "print (\"Hadamard gate: H=\")\n",
    "display(sympy.Matrix(H.matrix))\n",
    "\n",
    "print (\"H is of order 2:\")\n",
    "A=H*H\n",
    "print (\"H*H =\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "\n",
    "print (\"H operates on the Pauli gates by conjugation as a reflection: X<-->Z:\")\n",
    "A=H*X*H\n",
    "print(\"H*X*H = Z =\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=H*Z*H\n",
    "print(\"H*Z*H = X =\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=H*Y*H\n",
    "print(\"H*Y*H = Y =\")\n",
    "display(sympy.Matrix(A.matrix))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We therefore get the commutator relations:\n",
    "$$HX=ZH$$\n",
    "$$HZ=XH$$\n",
    "$$HY=YH$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Phase gate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Phase gate: S=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABXElEQVQ4EeWUMUvDQBTH/1f7pIamJm5FoQ6Kk9pRBz+BQ4qrg8UvYEFwcPITaEFEnMwmODm5emvFod/AfIMi4iCI8e7iveYgKR0F/0Py/u+Xl7x3OQ5hGKJAIgwDbKbvBQhemsZYKSI6R1Oww0A/yXq5HNo6cXzhsFoi1i0Dbh22BzyXsTtgFIB+e3Hr1FBRUsyEZp1i5n8BR/0JTBYzoeqikjqo741KesE9cFA2wz6wVTZ7JRGPzE6f1voYSwyuu8zG6VxEU/y/3OMc/pO6+mCHRzbBXJvX8xwLQwdWpGW0jHrsMG3IrLXXQ+NNW0dk2Hwb1W8nrw0Z1lLsQ1ur5raKyLBXidlPm9d3uasuxEztSZafqK0Eyt4pUc3XCWiXMdVLw+nFdJ0xLwY5M9R6XEcPmDlTjtVKpH0nNrDYZaCCyO8wW7o5ySN4V8qS6dPJs/ljbLXsbG3Gk87WH5XWb+uKMXPsAAAAAElFTkSuQmCC\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & i\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0⎤\n",
       "⎢    ⎥\n",
       "⎣0  ⅈ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Z=S*S, thus S has order 4, and the inverse of S is S*Z:\n",
      "S*S = Z =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABQ0lEQVQ4EWMQFBRkwAdA8vr/P+NTwrD+/y8GFbwqQJJRxKtJEsAw7czkC1AxsDmMxf0YajgeMOoiq2FgmI+hJoiB4RQhNcsZGN5DNULdjGkOMED8H0AMwqWGEaQmAL8a3j8MDPkTiFBzAL8aRqA5/gTMYQC65/0D/OYwrGJgiCfk92gGBguIMbA4xQwfpgeM21DUVO1Xh7oPKszAwHhyegKKGrgMVgYJ6QerfpjgqDmwkMBOQ8KH56QtVmk2RZAwRE0fg9AFLIrELT7C1bAqMPAswKKGgROhhquAgQ/MQ1eHpIbfgIHlH7o8iI+kRh6o5isBNfcPMLD9JEINMD9hAmS7DjCwIJsjoQQCaijuAbqZj5CbuRYwsBLyO+sGBuYGTNeg2MWgxyCdQEiNzMwybErYV3+qBIoP33yhSrCOm0VMHQcAMdRoSULFp7cAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & -1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0 ⎤\n",
       "⎢     ⎥\n",
       "⎣0  -1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The inverse of S: Sdg = S*Z =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEIAAAAzBAMAAADRBMO/AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABRklEQVQ4EWMQFBRkwA1Asvr/P+NWwLD+/y8GFTzyIKkoIlWwKWIYdGbyBYgY2Axxi4/oKjgeMOoiqWDgxFARxMBwCr+K5QwM7wXASiAuxTQDGAL+D/CpYASpCMCngvcPA0P+BIIqDuBTwQg0wx+vGQxAd7x/gM8MhlUMDPH4fRvNwGABNgIac5jhwfSAcRuSCvbVnyohXDjJeHJ6ApIKuDg2BrHpA5temNioGbCQgNCQ8IBnH1RJBk4DaK5EZB80FUwHoCoQ2QdNBYgLtgWRfXCpQGQfHCqQsg+qCklLqC1I2QdVxQFvZBUHUCVBPN4HoMQMcilS9oEok1ACATVGhp9QFUjZB6ICRvKBihWwbxHZByYHoTkKYCoQ2QdVhfyDA1AzENkHVYU/bwBUBSL7oKrgmgrkQ+IWVQKVN5RUqBKogWYRroEAxcxpgI+1oIEAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & - i\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0 ⎤\n",
       "⎢     ⎥\n",
       "⎣0  -ⅈ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Indeed, S*Sdg =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABOElEQVQ4EWMQFBRkwAIYBQUFGPT/f8YixcD1//8CBhVsMiAxViLkkgRAKuHgzOQLMH2Mxf0ochwPGHVhcgwM81HkghgYTuGSW87A8F6AgRXqFlR9QE/5P8AuxwiSC8Aux/uHgSF/Ah65A9jlGIH6/HHoYwDa9x6HWxhWMTDE4/JDNAODBS6/Mz1g3AaXq9qvPoEBARhPTk+AyyGEkVisRMQfknI4c4To4zlpC/cyiMGmCCRYIWHWxyAETMhwIG7xEchmBcuxKjDwLADy4IATIcdVwMAH4sEBkhy/AQPLP7gEkIEkJw+U+4pD7v4BBrafeOSAaRIBkM08wMCCSx/QLXy43MK1gIEVlx9YNzAwNyBsQ/EDgx6DdAIuOZmZZchS7Ks/VcLCE1kcwWYdXGlXFVfZKrkAX9kKAIdJdTXUNN/CAAAAAElFTkSuQmCC\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & 1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0⎤\n",
       "⎢    ⎥\n",
       "⎣0  1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "S = QuantumMatrix(  [[1,0],  [0,sympy.I]])\n",
    "print (\"Phase gate: S=\")\n",
    "display(sympy.Matrix(S.matrix))\n",
    "\n",
    "print (\"Z=S*S, thus S has order 4, and the inverse of S is S*Z:\")\n",
    "A=S*S\n",
    "print (\"S*S = Z =\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "print (\"The inverse of S: Sdg = S*Z =\")\n",
    "Sdg = S*Z\n",
    "display(sympy.Matrix(Sdg.matrix))\n",
    "print (\"Indeed, S*Sdg =\")\n",
    "A = S*Sdg\n",
    "display(sympy.Matrix(A.matrix))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "S operates on the Pauli gates by conjugation as a reflection: Y<-->Z:\n",
      "S*X*Sdg = Y =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGaJdiLNVLurMu++UplCAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABPUlEQVQ4EWMQFBRkwAdA8vr/P+NTwrD//28GFbwqQJLRJKlhS7fAMJFXEdWcWQxCDWiKZCw/oqhhVWBg24CmhoEdVQ33AQYusAiyOjQ1/AYMLL+Q5UFsNDXyQDVfCajpT2Dg/U6Emm8E1MgnMLAQMgfoZi5CbubewMBKyO+sDxiYJxBwD4MWg9wFQmrEys+iK+HZ9+k4UIy0tIFuCII/ag4iLLCxyAifSwIoBqUVNwD5KOYwHp6PooZzAaMGuhoGhnoUNUEMDNmE1OxhYFgP1IRiF7o5wILJfwF+NYwgNQH41XAA89v9AiLUJEDVME5SAoELaO5hBJrjT8AcBqB71hNwM8NuBoZ4AfzuYYhjYLAkFIZMCxjfYqg5/V4H6EY4YEyvAfoDPZzh0sgMtLhAloKzB58aVYJ1XDUxdRwA7L5mXz5GEq8AAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}0 & 1\\\\-1 & 0\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡0   1⎤\n",
       "⎢     ⎥\n",
       "⎣-1  0⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "S*Y*Sdg = X =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGaJdiLNVLurMu++UplCAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABJ0lEQVQ4EWMQFBRkwAIYBQUFGPT/f8YixcD9//8GBhVsMiAxVsJybOkWKLp5FRH6ZjEINSBJylh+hMuxKjCwbUCSY2BHyHEfYOAC8eAASY7fgIHlF1wCyECSkwfKfcUh15/AwPsdj9w3HHLyCQwsuPQB3cKFyy3cGxhYcfmB9QED8wQc9jFoMchdwCUnVn4WWYpn36fjRMURsiY4m4i4hatFZgwnfZcEkH3GkFbcAAtPxsPzUeQ4FzBqwOQYGOpR5IIYGLJxye1hYFgvAM9HqPqAGdJ/AXY5RpBcAHY5DmBavV+ARy4BuxwjUJ8/Dn0MQPvW43ALw24GhnhcfohjYLDE5XemBYxv4XKn3+sUIAU2Y3rNBbgckjiCOcjSmSquslV8A76yFQDlSHUUUuAZNAAAAABJRU5ErkJggg==\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}0 & 1\\\\1 & 0\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡0  1⎤\n",
       "⎢    ⎥\n",
       "⎣1  0⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "S*Z*Sdg = Z =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABQ0lEQVQ4EWMQFBRkwAdA8vr/P+NTwrD+/y8GFbwqQJJRxKtJEsAw7czkC1AxsDmMxf0YajgeMOoiq2FgmI+hJoiB4RQhNcsZGN5DNULdjGkOMED8H0AMwqWGEaQmAL8a3j8MDPkTiFBzAL8aRqA5/gTMYQC65/0D/OYwrGJgiCfk92gGBguIMbA4xQwfpgeM21DUVO1Xh7oPKszAwHhyegKKGrgMVgYJ6QerfpjgqDmwkMBOQ8KH56QtVmk2RZAwRE0fg9AFLIrELT7C1bAqMPAswKKGgROhhquAgQ/MQ1eHpIbfgIHlH7o8iI+kRh6o5isBNfcPMLD9JEINMD9hAmS7DjCwIJsjoQQCaijuAbqZj5CbuRYwsBLyO+sGBuYGTNeg2MWgxyCdQEiNzMwybErYV3+qBIoP33yhSrCOm0VMHQcAMdRoSULFp7cAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & -1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0 ⎤\n",
       "⎢     ⎥\n",
       "⎣0  -1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "We therefore get the commutator relations:\n",
      "S*X = Y*S and Sdg*Y = X*Sdg\n",
      "S*Y = X*S and Sdg*X = Y*Sdg\n",
      "S*Z = Z*S = Sdg and Sdg*Z = Z*Sdg = S\n"
     ]
    }
   ],
   "source": [
    "print (\"S operates on the Pauli gates by conjugation as a reflection: Y<-->Z:\")\n",
    "A = S*X*Sdg # =Y\n",
    "print (\"S*X*Sdg = Y =\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "print (\"S*Y*Sdg = X =\")\n",
    "A = S*Y*Sdg # =X\n",
    "display(sympy.Matrix(A.matrix))\n",
    "print (\"S*Z*Sdg = Z =\")\n",
    "A = S*Z*Sdg # =Z\n",
    "display(sympy.Matrix(A.matrix))\n",
    "\n",
    "print (\"We therefore get the commutator relations:\")\n",
    "print (\"S*X = Y*S and Sdg*Y = X*Sdg\")\n",
    "print (\"S*Y = X*S and Sdg*X = Y*Sdg\")\n",
    "print (\"S*Z = Z*S = Sdg and Sdg*Z = Z*Sdg = S\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The axis swap group"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Let: V = H*S*H*S =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEIAAAAzBAMAAADRBMO/AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA10lEQVQ4EWMQFBRkwA1Asvr/P+NWwLD+/y8GFTzyIKkoElQkCWAYBhaCmcFY3I+uAioEU8HAMB9dBVRoVAU8bMFBRNXwqNqvPgFuPIQBEULYgiYN546qgAcFmEH98OA0QLEBzEW1hekAigowF1UFijyUQ3UVkpYo1kC4KLYc8EZRAeEiq+B9YIGsAsoFq5BQAgE1RoafyCqgXGQzGPg+IquAclFUcBSgqIBwUVTIPziArATCRVHhzxuArALCRVHBNRVZAQOEi6ICRR7GGUoqVAnUQLMI10AA+a5K6nJmz2YAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 1\\\\- i & i\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1   1⎤\n",
       "⎢     ⎥\n",
       "⎣-ⅈ  ⅈ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "V is of order 3:\n",
      "V*V*V =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABOElEQVQ4EWMQFBRkwAIYBQUFGPT/f8YixcD1//8CBhVsMiAxViLkkgRAKuHgzOQLMH2Mxf0ochwPGHVhcgwM81HkghgYTuGSW87A8F6AgRXqFlR9QE/5P8AuxwiSC8Aux/uHgSF/Ah65A9jlGIH6/HHoYwDa9x6HWxhWMTDE4/JDNAODBS6/Mz1g3AaXq9qvPoEBARhPTk+AyyGEkVisRMQfknI4c4To4zlpC/cyiMGmCCRYIWHWxyAETMhwIG7xEchmBcuxKjDwLADy4IATIcdVwMAH4sEBkhy/AQPLP7gEkIEkJw+U+4pD7v4BBrafeOSAaRIBkM08wMCCSx/QLXy43MK1gIEVlx9YNzAwNyBsQ/EDgx6DdAIuOZmZZchS7Ks/VcLCE1kcwWYdXGlXFVfZKrkAX9kKAIdJdTXUNN/CAAAAAElFTkSuQmCC\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & 1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0⎤\n",
       "⎢    ⎥\n",
       "⎣0  1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hence, V = Sdg*H =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEIAAAAzBAMAAADRBMO/AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA10lEQVQ4EWMQFBRkwA1Asvr/P+NWwLD+/y8GFTzyIKkoElQkCWAYBhaCmcFY3I+uAioEU8HAMB9dBVRoVAU8bMFBRNXwqNqvPgFuPIQBEULYgiYN546qgAcFmEH98OA0QLEBzEW1hekAigowF1UFijyUQ3UVkpYo1kC4KLYc8EZRAeEiq+B9YIGsAsoFq5BQAgE1RoafyCqgXGQzGPg+IquAclFUcBSgqIBwUVTIPziArATCRVHhzxuArALCRVHBNRVZAQOEi6ICRR7GGUoqVAnUQLMI10AA+a5K6nJmz2YAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 1\\\\- i & i\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1   1⎤\n",
       "⎢     ⎥\n",
       "⎣-ⅈ  ⅈ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The inverse of V is: W = S*Z*H*S*Z*H = H*S = \n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEIAAAAzBAMAAADRBMO/AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA6klEQVQ4EWMQFBRkwA1Asvr/P+NWwLD+/y8GFTzyIKkoIlWwKWIaxGkAEQObIW7xEVMF0wEkFQycWFTA9EDcQSMVkpZQa3DacsCbgAreBxYEVDAy/CSggoEPFgA43cFRQMgM+QcHIEpwmuHPG4Ckgn31p0qomXCKayqUCTEDLo6FMaoCNVCoFx7YchTILlCuAtuCNUeBVIByFcQdNMovIEvAAK8t4FyFVwU4V+FTAclVWFVIKIGAGiRXYVUBcyQ4V+FVAc5VeFWAcxVeFeBcBVaBLUeB3ALOVRAzYE7DRg8lFaoEaqBZhGsgACj0UXqzDQjHAAAAAElFTkSuQmCC\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & i\\\\1 & - i\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  ⅈ ⎤\n",
       "⎢     ⎥\n",
       "⎣1  -ⅈ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Indeed, W = V*V =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEIAAAAzBAMAAADRBMO/AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA6klEQVQ4EWMQFBRkwA1Asvr/P+NWwLD+/y8GFTzyIKkoIlWwKWIaxGkAEQObIW7xEVMF0wEkFQycWFTA9EDcQSMVkpZQa3DacsCbgAreBxYEVDAy/CSggoEPFgA43cFRQMgM+QcHIEpwmuHPG4Ckgn31p0qomXCKayqUCTEDLo6FMaoCNVCoFx7YchTILlCuAtuCNUeBVIByFcQdNMovIEvAAK8t4FyFVwU4V+FTAclVWFVIKIGAGiRXYVUBcyQ4V+FVAc5VeFWAcxVeFeBcBVaBLUeB3ALOVRAzYE7DRg8lFaoEaqBZhGsgACj0UXqzDQjHAAAAAElFTkSuQmCC\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & i\\\\1 & - i\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  ⅈ ⎤\n",
       "⎢     ⎥\n",
       "⎣1  -ⅈ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "V = H*S*H*S\n",
    "print (\"Let: V = H*S*H*S =\")\n",
    "display(sympy.Matrix(V.matrix))\n",
    "\n",
    "print (\"V is of order 3:\")\n",
    "A=V*V*V\n",
    "print (\"V*V*V =\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "\n",
    "print (\"Hence, V = Sdg*H =\")\n",
    "A=Sdg*H\n",
    "display(sympy.Matrix(A.matrix))\n",
    "\n",
    "print (\"The inverse of V is: W = S*Z*H*S*Z*H = H*S = \")\n",
    "W=H*S\n",
    "display(sympy.Matrix(W.matrix))\n",
    "\n",
    "print (\"Indeed, W = V*V =\")\n",
    "A=V*V\n",
    "display(sympy.Matrix(A.matrix))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "V operates on the Pauli gates by conjugation as a rotation: Z-->X-->Y-->Z:\n",
      "W*X*V = Y =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGaJdiLNVLurMu++UplCAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABPUlEQVQ4EWMQFBRkwAdA8vr/P+NTwrD//28GFbwqQJLRJKlhS7fAMJFXEdWcWQxCDWiKZCw/oqhhVWBg24CmhoEdVQ33AQYusAiyOjQ1/AYMLL+Q5UFsNDXyQDVfCajpT2Dg/U6Emm8E1MgnMLAQMgfoZi5CbubewMBKyO+sDxiYJxBwD4MWg9wFQmrEys+iK+HZ9+k4UIy0tIFuCII/ag4iLLCxyAifSwIoBqUVNwD5KOYwHp6PooZzAaMGuhoGhnoUNUEMDNmE1OxhYFgP1IRiF7o5wILJfwF+NYwgNQH41XAA89v9AiLUJEDVME5SAoELaO5hBJrjT8AcBqB71hNwM8NuBoZ4AfzuYYhjYLAkFIZMCxjfYqg5/V4H6EY4YEyvAfoDPZzh0sgMtLhAloKzB58aVYJ1XDUxdRwA7L5mXz5GEq8AAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}0 & 1\\\\-1 & 0\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡0   1⎤\n",
       "⎢     ⎥\n",
       "⎣-1  0⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "W*Y*V = Z =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABQ0lEQVQ4EWMQFBRkwAdA8vr/P+NTwrD+/y8GFbwqQJJRxKtJEsAw7czkC1AxsDmMxf0YajgeMOoiq2FgmI+hJoiB4RQhNcsZGN5DNULdjGkOMED8H0AMwqWGEaQmAL8a3j8MDPkTiFBzAL8aRqA5/gTMYQC65/0D/OYwrGJgiCfk92gGBguIMbA4xQwfpgeM21DUVO1Xh7oPKszAwHhyegKKGrgMVgYJ6QerfpjgqDmwkMBOQ8KH56QtVmk2RZAwRE0fg9AFLIrELT7C1bAqMPAswKKGgROhhquAgQ/MQ1eHpIbfgIHlH7o8iI+kRh6o5isBNfcPMLD9JEINMD9hAmS7DjCwIJsjoQQCaijuAbqZj5CbuRYwsBLyO+sGBuYGTNeg2MWgxyCdQEiNzMwybErYV3+qBIoP33yhSrCOm0VMHQcAMdRoSULFp7cAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & -1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0 ⎤\n",
       "⎢     ⎥\n",
       "⎣0  -1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "W*Z*V = X = \n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGaJdiLNVLurMu++UplCAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABJ0lEQVQ4EWMQFBRkwAIYBQUFGPT/f8YixcD9//8GBhVsMiAxVsJybOkWKLp5FRH6ZjEINSBJylh+hMuxKjCwbUCSY2BHyHEfYOAC8eAASY7fgIHlF1wCyECSkwfKfcUh15/AwPsdj9w3HHLyCQwsuPQB3cKFyy3cGxhYcfmB9QED8wQc9jFoMchdwCUnVn4WWYpn36fjRMURsiY4m4i4hatFZgwnfZcEkH3GkFbcAAtPxsPzUeQ4FzBqwOQYGOpR5IIYGLJxye1hYFgvAM9HqPqAGdJ/AXY5RpBcAHY5DmBavV+ARy4BuxwjUJ8/Dn0MQPvW43ALw24GhnhcfohjYLDE5XemBYxv4XKn3+sUIAU2Y3rNBbgckjiCOcjSmSquslV8A76yFQDlSHUUUuAZNAAAAABJRU5ErkJggg==\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}0 & 1\\\\1 & 0\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡0  1⎤\n",
       "⎢    ⎥\n",
       "⎣1  0⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "print (\"V operates on the Pauli gates by conjugation as a rotation: Z-->X-->Y-->Z:\")\n",
    "A=W*X*V\n",
    "print(\"W*X*V = Y =\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=W*Y*V\n",
    "print(\"W*Y*V = Z =\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=W*Z*V\n",
    "print(\"W*Z*V = X = \")\n",
    "display(sympy.Matrix(A.matrix))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The 24 elements in the Clifford group $C_1$\n",
    "\n",
    "Since $C_1/P_1 \\cong Sp(2) \\cong S_3$, we can explicitly present each element of $C_1$ as a product $AB$ where $A \\in \\{ I, V, W, H, HV, HW\\}$ and $B \\in P_1=\\{I,X,Y,Z\\}$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABOElEQVQ4EWMQFBRkwAIYBQUFGPT/f8YixcD1//8CBhVsMiAxViLkkgRAKuHgzOQLMH2Mxf0ochwPGHVhcgwM81HkghgYTuGSW87A8F6AgRXqFlR9QE/5P8AuxwiSC8Aux/uHgSF/Ah65A9jlGIH6/HHoYwDa9x6HWxhWMTDE4/JDNAODBS6/Mz1g3AaXq9qvPoEBARhPTk+AyyGEkVisRMQfknI4c4To4zlpC/cyiMGmCCRYIWHWxyAETMhwIG7xEchmBcuxKjDwLADy4IATIcdVwMAH4sEBkhy/AQPLP7gEkIEkJw+U+4pD7v4BBrafeOSAaRIBkM08wMCCSx/QLXy43MK1gIEVlx9YNzAwNyBsQ/EDgx6DdAIuOZmZZchS7Ks/VcLCE1kcwWYdXGlXFVfZKrkAX9kKAIdJdTXUNN/CAAAAAElFTkSuQmCC\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & 1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0⎤\n",
       "⎢    ⎥\n",
       "⎣0  1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "X=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGaJdiLNVLurMu++UplCAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABJ0lEQVQ4EWMQFBRkwAIYBQUFGPT/f8YixcD9//8GBhVsMiAxVsJybOkWKLp5FRH6ZjEINSBJylh+hMuxKjCwbUCSY2BHyHEfYOAC8eAASY7fgIHlF1wCyECSkwfKfcUh15/AwPsdj9w3HHLyCQwsuPQB3cKFyy3cGxhYcfmB9QED8wQc9jFoMchdwCUnVn4WWYpn36fjRMURsiY4m4i4hatFZgwnfZcEkH3GkFbcAAtPxsPzUeQ4FzBqwOQYGOpR5IIYGLJxye1hYFgvAM9HqPqAGdJ/AXY5RpBcAHY5DmBavV+ARy4BuxwjUJ8/Dn0MQPvW43ALw24GhnhcfohjYLDE5XemBYxv4XKn3+sUIAU2Y3rNBbgckjiCOcjSmSquslV8A76yFQDlSHUUUuAZNAAAAABJRU5ErkJggg==\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}0 & 1\\\\1 & 0\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡0  1⎤\n",
       "⎢    ⎥\n",
       "⎣1  0⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Y=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGaJdiLNVLurMu++UplCAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABPUlEQVQ4EWMQFBRkwAdA8vr/P+NTwrD//28GFbwqQJLRJKlhS7fAMJFXEdWcWQxCDWiKZCw/oqhhVWBg24CmhoEdVQ33AQYusAiyOjQ1/AYMLL+Q5UFsNDXyQDVfCajpT2Dg/U6Emm8E1MgnMLAQMgfoZi5CbubewMBKyO+sDxiYJxBwD4MWg9wFQmrEys+iK+HZ9+k4UIy0tIFuCII/ag4iLLCxyAifSwIoBqUVNwD5KOYwHp6PooZzAaMGuhoGhnoUNUEMDNmE1OxhYFgP1IRiF7o5wILJfwF+NYwgNQH41XAA89v9AiLUJEDVME5SAoELaO5hBJrjT8AcBqB71hNwM8NuBoZ4AfzuYYhjYLAkFIZMCxjfYqg5/V4H6EY4YEyvAfoDPZzh0sgMtLhAloKzB58aVYJ1XDUxdRwA7L5mXz5GEq8AAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}0 & 1\\\\-1 & 0\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡0   1⎤\n",
       "⎢     ⎥\n",
       "⎣-1  0⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Z=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABQ0lEQVQ4EWMQFBRkwAdA8vr/P+NTwrD+/y8GFbwqQJJRxKtJEsAw7czkC1AxsDmMxf0YajgeMOoiq2FgmI+hJoiB4RQhNcsZGN5DNULdjGkOMED8H0AMwqWGEaQmAL8a3j8MDPkTiFBzAL8aRqA5/gTMYQC65/0D/OYwrGJgiCfk92gGBguIMbA4xQwfpgeM21DUVO1Xh7oPKszAwHhyegKKGrgMVgYJ6QerfpjgqDmwkMBOQ8KH56QtVmk2RZAwRE0fg9AFLIrELT7C1bAqMPAswKKGgROhhquAgQ/MQ1eHpIbfgIHlH7o8iI+kRh6o5isBNfcPMLD9JEINMD9hAmS7DjCwIJsjoQQCaijuAbqZj5CbuRYwsBLyO+sGBuYGTNeg2MWgxyCdQEiNzMwybErYV3+qBIoP33yhSrCOm0VMHQcAMdRoSULFp7cAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & -1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0 ⎤\n",
       "⎢     ⎥\n",
       "⎣0  -1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "print (\"I=\")\n",
    "display(sympy.Matrix(I.matrix))\n",
    "print (\"X=\")\n",
    "display(sympy.Matrix(X.matrix))\n",
    "print (\"Y=\")\n",
    "display(sympy.Matrix(Y.matrix))\n",
    "print (\"Z=\")\n",
    "display(sympy.Matrix(Z.matrix))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "V=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEIAAAAzBAMAAADRBMO/AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA10lEQVQ4EWMQFBRkwA1Asvr/P+NWwLD+/y8GFTzyIKkoElQkCWAYBhaCmcFY3I+uAioEU8HAMB9dBVRoVAU8bMFBRNXwqNqvPgFuPIQBEULYgiYN546qgAcFmEH98OA0QLEBzEW1hekAigowF1UFijyUQ3UVkpYo1kC4KLYc8EZRAeEiq+B9YIGsAsoFq5BQAgE1RoafyCqgXGQzGPg+IquAclFUcBSgqIBwUVTIPziArATCRVHhzxuArALCRVHBNRVZAQOEi6ICRR7GGUoqVAnUQLMI10AA+a5K6nJmz2YAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 1\\\\- i & i\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1   1⎤\n",
       "⎢     ⎥\n",
       "⎣-ⅈ  ⅈ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "V*X=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEIAAAAzBAMAAADRBMO/AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA10lEQVQ4EWMQFBRkwA1Asvr/P+NWwLD+/y8GFTzyIKkoIlWwKWIYBBcCmyFu8RFdBUIIYgsnhgoGuNCoCnDoUT882Fd/qkSLGIQQsbGPZgAKd9QMlOAgOkcxcBqgaoTyQMLQMGU6gFUFSJieoS5pidUZYGGIOw54Y1UBFgar4H1ggU0FRBisgpHhJ4oKCSUQUIMIQ2zhwyw/QFrAwhAVHAUoZsA4YGGICvkHB2CiyDRYGKLCnzcAWQbGBgtDVHBNhQmi0GBhiAoUcTTOUFKhSqAGmkW4BgIAVSlRenFXXZUAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 1\\\\i & - i\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  1 ⎤\n",
       "⎢     ⎥\n",
       "⎣ⅈ  -ⅈ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "V*Y=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA4ElEQVQ4EWMQFBRkwAdA8vr/P+NTwrD+/y8GFbwqQJJRxKtJEsBqGpsi3BzG4n6sasQtPsLVMDDMx6qGgXN4qZFQAgE1hkHtr6r96hOwRCr76k+VQGES0gYWQxBCo+YgwgIbi4Tw4TTANAAuBjWH6QCmGrgYCXZhmoIkQrw5kpZI2qBMhBjEnAPemGoQYmA1vA8sMNQgiYHVMDL8xFCDJAaxiw9czqCqQ4hB1HAUoMqDeAgxiBr5BwcwFCHEIGr8eQMw1CDEIGq4pmIoYUCIQdRgqkAWGZpqVAnWcbOIqeMAuwhOMrAH0y8AAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & -1\\\\i & i\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  -1⎤\n",
       "⎢     ⎥\n",
       "⎣ⅈ  ⅈ ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "V*Z=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAFMAAAAzBAMAAAAZaClpAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA8UlEQVRIDWMQFBRkIAwYBQUFGPT/fyaskoHr//8FDCpEKAQpYSVLKZsiSC9WkCQAFGaFmypu8RGrMgYGxuJ+VKUMnLiUMjDMH6FKGZuUQCBhSIcA++pPlTgSQdV+9QnIyQWHMoQwKzxlIcRwsEaVDroQmIw9qkDC6G7Vwa4UJIyuFLtKsCg9lDJOBiZhTAARRnUAD8sGTIUMDBBhVKX3mBuwKYUIQ5TCCgcBfhQHoAqjmsrwXgCbqRBhNKXtWFUygIVRlTL+48GmFiKMqpTlw1VsSiHCqEoZVgZgUwoRRlOKVSFUcPgqVSWy6SC5gISmAwDxy2HhW2UztQAAAABJRU5ErkJggg==\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & -1\\\\- i & - i\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1   -1⎤\n",
       "⎢      ⎥\n",
       "⎣-ⅈ  -ⅈ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "print (\"V=\")\n",
    "display(sympy.Matrix(V.matrix))\n",
    "A=V*X\n",
    "print (\"V*X=\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=V*Y\n",
    "print (\"V*Y=\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=V*Z\n",
    "print (\"V*Z=\")\n",
    "display(sympy.Matrix(A.matrix))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "W=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEIAAAAzBAMAAADRBMO/AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA6klEQVQ4EWMQFBRkwA1Asvr/P+NWwLD+/y8GFTzyIKkoIlWwKWIaxGkAEQObIW7xEVMF0wEkFQycWFTA9EDcQSMVkpZQa3DacsCbgAreBxYEVDAy/CSggoEPFgA43cFRQMgM+QcHIEpwmuHPG4Ckgn31p0qomXCKayqUCTEDLo6FMaoCNVCoFx7YchTILlCuAtuCNUeBVIByFcQdNMovIEvAAK8t4FyFVwU4V+FTAclVWFVIKIGAGiRXYVUBcyQ4V+FVAc5VeFWAcxVeFeBcBVaBLUeB3ALOVRAzYE7DRg8lFaoEaqBZhGsgACj0UXqzDQjHAAAAAElFTkSuQmCC\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & i\\\\1 & - i\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  ⅈ ⎤\n",
       "⎢     ⎥\n",
       "⎣1  -ⅈ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "W*X=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAFMAAAAzBAMAAAAZaClpAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA70lEQVRIDWMQFBRkIAwYBQUFGPT/fyaskoHr//8FDCpEKAQpYSVPaZIASDN2MBnZVMbifjxKdZCVMjDMx6MUaBcrklvprZRx8gRiHcDDsoFYpfeYGwgpZWxSAoEEAX6iHcDwHhiORAZWOwOxShn/8RCrlOXDVRSlVfvVgY7HDlYGoCjFrgghyoqUBhCiWFmjSgddCOAqNlCKDFBk4i420IoMkGI8ZQErWnKhp1KMIgO3WzGKDNxKkYoMWNGAHgIwcYwiA7epGEUGHqXoRQZupRhFBm6l6EUGSCWuYmO0yACFDusCBlUimw6SC0hoOgAATP9embtrb+wAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & - i\\\\-1 & - i\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1   -ⅈ⎤\n",
       "⎢      ⎥\n",
       "⎣-1  -ⅈ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "W*Y=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEIAAAAzBAMAAADRBMO/AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA30lEQVQ4EWMQFBRkwA1Asvr/P+NWwLD+/y8GFTzyIKkoUlQkCWCYxmmAZAZjcT+mCqYDSCoYGOZjqkBzB21USFqi+hbTlgPeBFTwPrAgoIKR4ScBFQx8Hwmp4CggpEL+wQECYerPG4Csomq/+gSgociAayqQR1LsI+tGYo+agRQYZIQpmyKqfpQcBZIStwAlGSSAlqOAMpxoKkCKUeOFBirQcxSmO9BzFIYKpBwloQQCauh+wchRGGZg5ChMFeg5ClMFeo7CVIGWo4AK2Fd/qgRScDAMc5QqgRpoFuEaCABdQU4yD8yO7AAAAABJRU5ErkJggg==\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & i\\\\-1 & i\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1   ⅈ⎤\n",
       "⎢     ⎥\n",
       "⎣-1  ⅈ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "W*Z=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEIAAAAzBAMAAADRBMO/AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA4klEQVQ4EWMQFBRkwA1Asvr/P+NWwLD+/y8GFTzyIKkoIlWwKWI3iNMAaoa4xUfsKpgOwGzhxKECpA/iDhqqkLQkZMsBbwIqeB9Y4FIhoQQCaowMP3GpAIqDAR8oEPD6lqOAkAr5BwcImOHPGwBVwb76UyXYYjSCayrcFjQZFC6x6QNFExpn1AzUAIGEB7YcBcpNIABWgTVHgXITCEDMoGF+wW8LODfhdQc4N+FTAclN+FRAchM+FQzg3IRXBTg34VUBzk14VYBzE1wFthwFzk1wFSAGTjCUcoMqgRpoFuEaCAArcVF6iw8mmQAAAABJRU5ErkJggg==\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & - i\\\\1 & i\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  -ⅈ⎤\n",
       "⎢     ⎥\n",
       "⎣1  ⅈ ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "print (\"W=\")\n",
    "display(sympy.Matrix(W.matrix))\n",
    "A=W*X\n",
    "print (\"W*X=\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=W*Y\n",
    "print (\"W*Y=\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=W*Z\n",
    "print (\"W*Z=\")\n",
    "display(sympy.Matrix(A.matrix))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAJ1BMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAilU6eAAAADHRSTlMAEN2ZRGYyq812u+91lTu7AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAoUlEQVQ4EWMQFBRkwAdA8jpnDuNTwrDmzCkGFbwqQJJRxKtJEsAwjU0RJgQ2h7G4B0ONuMVBFDUMDHMw1DBwjqpBxAUdw6dqj/oEWOxAafbVhyqhTBLSBpohqNxRc1DDA51HQvhgyYMg0yD5EGceBCmB5kOoXVjSGEgRJB8OGzUSSiCgNrj9hSUPgqICmg9JSBsgXTjB4DNHlWAdN4uYOg4AYlROuMwACloAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 1\\\\1 & -1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  1 ⎤\n",
       "⎢     ⎥\n",
       "⎣1  -1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*X=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAJ1BMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAilU6eAAAADHRSTlMAEN2ZRGYyq812u+91lTu7AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAj0lEQVQ4EWMQFBRkwAdA8jpnDuNTwrDmzCkGFbwqQJJRpKlJEsAwkU0RxRzG4h4MNeIWB1HUMDDMwVDDwDmqBhEXdAyfqj3qE9AilX31oUqgEIlpA80QBHfUHERYYGORET5o+RAtD4IsQc+HmHkQpAotnWHkwaGlhrFJCQQShqS/0PLhsM+DqgTruFnE1HEA/wRPXX1E1RcAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 1\\\\-1 & 1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1   1⎤\n",
       "⎢     ⎥\n",
       "⎣-1  1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*Y=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAFYAAAAzBAMAAAD/QeItAAAAJ1BMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAilU6eAAAADHRSTlMAEN2ZRGYyq812u+91lTu7AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAoElEQVRIDWMQFBRkIAaA1OmcOUyMUoY1Z04xqBClEqQoijy1SQI4bWBTRDGXsbgHp1pxi4MoahkY5uBUy8A5stVKKIGAGsOQD4eqPeoTcCQe9tWHKoFSZKZJHIYihEfNhYTFIAwHHOUJWlkCcj6u8gSzLAGpxlGeYJQlw1MtYxO40EhADwfcZckQDAcc5cloWQKKSziIYlAluq0xi5S2BgCw2FEtaznbIQAAAABJRU5ErkJggg==\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & -1\\\\-1 & -1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1   -1⎤\n",
       "⎢      ⎥\n",
       "⎣-1  -1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*Z=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAJ1BMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAilU6eAAAADHRSTlMAEN2ZRGYyq812u+91lTu7AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAApElEQVQ4EWMQFBRkwAdA8jpnDuNTwrDmzCkGFbwqQJJRxKtJEsBqGpsi3BzG4h6sasQtDsLVMDDMwaqGgXN4qZFQAgE1hkHtr6o96hOwRCr76kOVQGES0gYWQxBCo+YgwgIbi4TwwZIHIfkPZC7YHGx5EJr/4Gqw5kFI/htVAy4zsZRRtAofLHkQmv+Q4gLExAlISD84zQBJ0NccVYJ13Cxi6jgAkiFOuHAgcfUAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & -1\\\\1 & 1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  -1⎤\n",
       "⎢     ⎥\n",
       "⎣1  1 ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "print (\"H=\")\n",
    "display(sympy.Matrix(H.matrix))\n",
    "A=H*X\n",
    "print (\"H*X=\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=H*Y\n",
    "print (\"H*Y=\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=H*Z\n",
    "print (\"H*Z=\")\n",
    "display(sympy.Matrix(A.matrix))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*V=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA8ElEQVQ4EWMQFBRkwAIYBQUFGPT/f8YixcD1//8CBhVsMiAxViLkkgRAKhGA0wCmj7G4H02O6QBMjoFhPpocyARWqH1UkpO0xG3mAW+ccrwPLHDKMTL8xCnHwPcRtxxHAW45+QcHcPrdnzcALle1X30C0BQ44JoKZLISEUdwHUiMUX3AwJiMFCAMDGyKQC4rLDx1kOXELZDjFlkGyOakghzjZJSoRTGTh2UDio3I9t1jbsApJ8CP20yG9wI49TG0o0ihuIXxHw+KJLJbWD5cxSnHsDIAWY599adKpLBGloKyWWHxMDjkVHGVrZIL8JWtAF+5XCw21ztRAAAAAElFTkSuQmCC\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & i\\\\i & 1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  ⅈ⎤\n",
       "⎢    ⎥\n",
       "⎣ⅈ  1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*V*X=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAE8AAAAzBAMAAAAk+kgPAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABA0lEQVRIDWMQFBRkIAQYBQUFGPT/fyakjoHr//8FDCoElYEUsJKhMEkApBMrmIxkImNxP26FOkgKGRjm41YItIYV4UY6KmScPIE4q3lYNhCn8B5zA36FjE1KIJAgwE+k1QzvgQFHVPC0MxCnkPEfD3EKWT5cRVZYtV8d6GasYGUAskKsShCCrIi4RghiY40qxBYqcDHaBw8wq6MCNkUInxUtCoFZHQWIW3yE8FnRFKKoAnE46aQQnNVRbcduNTirE6MQnNXxKUTJ6vgUwuVAWR0VYHcjAyirowLsCsFZnRiF4KxOjEIGUFZHAeyrP1WCBVgJxTVM23BTqEpUxS65gOiKHQCbJGBUhDKvcgAAAABJRU5ErkJggg==\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & - i\\\\- i & 1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1   -ⅈ⎤\n",
       "⎢      ⎥\n",
       "⎣-ⅈ  1 ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*V*Y=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAFMAAAAzBAMAAAAZaClpAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABEElEQVRIDWMQFBRkIAwYBQUFGPT/fyaskoHr//8FDCpEKAQpYSVLKZsiSC8mmAwVYoWbKm7xEVMZSEQHKswKV8rAiUMpVCXDACllnDwB6gKCDuBh2UCs0nvMDcQqFeAn2gEM7wWINZWhHaqSgZVQFDD+4yHWVJYPVzGUsq/+VAkVRKFWBmAoRZHHxmFFuBWbNLLYqNJBFwKw8gE5mhgYkkBpFt2tsPIBWSljcT82pchKEOz59FKKKB8QloNYWByAKB8IKkWUDziVMjYpgUAConwAKYWJYnUAonzAaSpcAl4+wEXADCzeQpQPBJUiygeCShng5QOK0qr96hMwkwuKElQO67AtMlSJbDpILiCh6QAAH4RgVHHMPx8AAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & i\\\\- i & -1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1   ⅈ ⎤\n",
       "⎢      ⎥\n",
       "⎣-ⅈ  -1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*V*Z=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABCElEQVQ4EWMQFBRkwAdA8vr/P+NTwrD+/y8GFbwqQJJRxKtJEsBuGqcBzBzG4n4capgOwNQwMMzHoQZsOtQ9NFYjaQmyDL9dB7wJquF9YIFbjYQSCKgxMvzErQYkAwJ8H0EkfvdwFBBWI//gAEFz/HkD4Gqq9qtPAJmKDrimgkRISBvoBqDwR81BCQ4MDgnhA85rGAYwsCmCxKDmgPMahhpxC+Q0hiENEeCkgRpIXsO0ENkuSF7Dqwaa1/CqgeY1uBpoFmRgQLYLktfgauAMZDWQvAaXgjOQ1UDyGlwKzkBWA8lrcCk4A1kNJK/BpWAM9tWfKoFsEtIGTCdWevCZo0qwjptFTB0HALDXTxpU7w0IAAAAAElFTkSuQmCC\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & - i\\\\i & -1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  -ⅈ⎤\n",
       "⎢     ⎥\n",
       "⎣ⅈ  -1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "print (\"H*V=\")\n",
    "A=H*V\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=H*V*X\n",
    "print (\"H*V*X=\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=H*V*Y\n",
    "print (\"H*V*Y=\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=H*V*Z\n",
    "print (\"H*V*Z=\")\n",
    "display(sympy.Matrix(A.matrix))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*W=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABXElEQVQ4EeWUMUvDQBTH/1f7pIamJm5FoQ6Kk9pRBz+BQ4qrg8UvYEFwcPITaEFEnMwmODm5emvFod/AfIMi4iCI8e7iveYgKR0F/0Py/u+Xl7x3OQ5hGKJAIgwDbKbvBQhemsZYKSI6R1Oww0A/yXq5HNo6cXzhsFoi1i0Dbh22BzyXsTtgFIB+e3Hr1FBRUsyEZp1i5n8BR/0JTBYzoeqikjqo741KesE9cFA2wz6wVTZ7JRGPzE6f1voYSwyuu8zG6VxEU/y/3OMc/pO6+mCHRzbBXJvX8xwLQwdWpGW0jHrsMG3IrLXXQ+NNW0dk2Hwb1W8nrw0Z1lLsQ1ur5raKyLBXidlPm9d3uasuxEztSZafqK0Eyt4pUc3XCWiXMdVLw+nFdJ0xLwY5M9R6XEcPmDlTjtVKpH0nNrDYZaCCyO8wW7o5ySN4V8qS6dPJs/ljbLXsbG3Gk87WH5XWb+uKMXPsAAAAAElFTkSuQmCC\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & i\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0⎤\n",
       "⎢    ⎥\n",
       "⎣0  ⅈ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*W*X=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGaJdiLNVLurMu++UplCAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABQklEQVQ4EWMQFBRkwAIYBQUFGPT/f8YixcD9//8GBhVsMiAxVsJybOkWKLp5FRH6ZjEINSBJylh+hMuxKjCwbUCSY2BHyHEfYOAC8eAASY7fgIHlF1wCyECSkwfKfcUh15/AwPsdj9w3HHLyCQwsuPQB3cKFyy3cGxhYcfmB9QED8wQc9jFoMchdwCUnVn4WWYpn36fjRMURsiY4m4i4hatFZgwrfcXIPmNIK25ACk81ZDnOBYwaSHLIUgxBDAzZuOT2MDCsF8CRj4AZ0n8BTI6xuADJUEaQXABMjo3lAZIcBzCt3i+AyXWhJCWwXAJMToAfxUygPn+4PpCzkADQvvVwtzDMQZJhYNjNwBAP9wPjLzZkyTgGBku431k+tCLLMS1gfAuXY9gegCzHmF5zASGHLANjD7J0poqrbBXfgK9sBQAk4HMz4HAl4AAAAABJRU5ErkJggg==\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}0 & 1\\\\i & 0\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡0  1⎤\n",
       "⎢    ⎥\n",
       "⎣ⅈ  0⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*W*Y=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEIAAAAzBAMAAADRBMO/AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGaJdiLNVLurMu++UplCAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABKklEQVQ4EWMQFBRkwA1Asvr/P+NWwLD//28GFTzyIKlo4lWwpVtgGHZJANmMWQxCDahKGA/PR1bBqsDAtgFVBQNDPbIK7gMMXB/xquA3YGD5hVeFPFDFV7wq+hMYeL8TVPENrwr5BAYW/GYAXcqF36XcGxhY8fuW9QED8wS87mDQYpC7gF+FWPlZdAWn3+sUkBT76AbA+SSkILgedMZINoPdADk0IJkMNTyYEpBVQDIZqgpkeQZoJsOjAprJ8KiAZjIUFeLmyNZAMxmKigQ/ZBXQTIasgmOBJboKYCYDq5BUAgFdRgaUPAXNZMhmoJUP0EyGooLzALIt0EyGokJ+QQKSEmgmQ1HhzxGApAKayVBUcJciK2CAZDIUFSjyMM5QUqFKoAaqJlwDAQCf7lvwhr5RSAAAAABJRU5ErkJggg==\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}0 & 1\\\\- i & 0\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡0   1⎤\n",
       "⎢     ⎥\n",
       "⎣-ⅈ  0⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*W*Z=\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEIAAAAzBAMAAADRBMO/AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABRklEQVQ4EWMQFBRkwA1Asvr/P+NWwLD+/y8GFTzyIKkoIlWwKWIYdGbyBYgY2Axxi4/oKjgeMOoiqWDgxFARxMBwCr+K5QwM7wXASiAuxTQDGAL+D/CpYASpCMCngvcPA0P+BIIqDuBTwQg0wx+vGQxAd7x/gM8MhlUMDPH4fRvNwGABNgIac5jhwfSAcRuSCvbVnyohXDjJeHJ6ApIKuDg2BrHpA5temNioGbCQgNCQ8IBnH1RJBk4DaK5EZB80FUwHoCoQ2QdNBYgLtgWRfXCpQGQfHCqQsg+qCklLqC1I2QdVxQFvZBUHUCVBPN4HoMQMcilS9oEok1ACATVGhp9QFUjZB6ICRvKBihWwbxHZByYHoTkKYCoQ2QdVhfyDA1AzENkHVYU/bwBUBSL7oKrgmgrkQ+IWVQKVN5RUqBKogWYRroEAxcxpgI+1oIEAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & - i\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0 ⎤\n",
       "⎢     ⎥\n",
       "⎣0  -ⅈ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "print (\"H*W=\")\n",
    "A=H*W\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=H*W*X\n",
    "print (\"H*W*X=\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=H*W*Y\n",
    "print (\"H*W*Y=\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=H*W*Z\n",
    "print (\"H*W*Z=\")\n",
    "display(sympy.Matrix(A.matrix))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "### An alternative approach to the elements in the Clifford group $C_1$\n",
    "\n",
    "There are certain elements in the group $C_1$ that can be written with less gates (in particular, less Hadamard gates)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*V = H*H*S*H*S = S*H*S =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA8ElEQVQ4EWMQFBRkwAIYBQUFGPT/f8YixcD1//8CBhVsMiAxViLkkgRAKhGA0wCmj7G4H02O6QBMjoFhPpocyARWqH1UkpO0xG3mAW+ccrwPLHDKMTL8xCnHwPcRtxxHAW45+QcHcPrdnzcALle1X30C0BQ44JoKZLISEUdwHUiMUX3AwJiMFCAMDGyKQC4rLDx1kOXELZDjFlkGyOakghzjZJSoRTGTh2UDio3I9t1jbsApJ8CP20yG9wI49TG0o0ihuIXxHw+KJLJbWD5cxSnHsDIAWY599adKpLBGloKyWWHxMDjkVHGVrZIL8JWtAF+5XCw21ztRAAAAAElFTkSuQmCC\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & i\\\\i & 1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  ⅈ⎤\n",
       "⎢    ⎥\n",
       "⎣ⅈ  1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*V*Y = H*H*S*H*S*Y = S*H*S*Y = S*H*X*S = S*Z*H*S = Sdg*H*S =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAFMAAAAzBAMAAAAZaClpAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABEElEQVRIDWMQFBRkIAwYBQUFGPT/fyaskoHr//8FDCpEKAQpYSVLKZsiSC8mmAwVYoWbKm7xEVMZSEQHKswKV8rAiUMpVCXDACllnDwB6gKCDuBh2UCs0nvMDcQqFeAn2gEM7wWINZWhHaqSgZVQFDD+4yHWVJYPVzGUsq/+VAkVRKFWBmAoRZHHxmFFuBWbNLLYqNJBFwKw8gE5mhgYkkBpFt2tsPIBWSljcT82pchKEOz59FKKKB8QloNYWByAKB8IKkWUDziVMjYpgUAConwAKYWJYnUAonzAaSpcAl4+wEXADCzeQpQPBJUiygeCShng5QOK0qr96hMwkwuKElQO67AtMlSJbDpILiCh6QAAH4RgVHHMPx8AAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & i\\\\- i & -1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1   ⅈ ⎤\n",
       "⎢      ⎥\n",
       "⎣-ⅈ  -1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*V*Z = H*H*S*H*S*Z = S*H*Sdg =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAzBAMAAADY72PFAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABCElEQVQ4EWMQFBRkwAdA8vr/P+NTwrD+/y8GFbwqQJJRxKtJEsBuGqcBzBzG4n4capgOwNQwMMzHoQZsOtQ9NFYjaQmyDL9dB7wJquF9YIFbjYQSCKgxMvzErQYkAwJ8H0EkfvdwFBBWI//gAEFz/HkD4Gqq9qtPAJmKDrimgkRISBvoBqDwR81BCQ4MDgnhA85rGAYwsCmCxKDmgPMahhpxC+Q0hiENEeCkgRpIXsO0ENkuSF7Dqwaa1/CqgeY1uBpoFmRgQLYLktfgauAMZDWQvAaXgjOQ1UDyGlwKzkBWA8lrcCk4A1kNJK/BpWAM9tWfKoFsEtIGTCdWevCZo0qwjptFTB0HALDXTxpU7w0IAAAAAElFTkSuQmCC\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & - i\\\\i & -1\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  -ⅈ⎤\n",
       "⎢     ⎥\n",
       "⎣ⅈ  -1⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "print (\"H*V = H*H*S*H*S = S*H*S =\")\n",
    "A=S*H*S #H*V\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=Sdg*H*S #H*V*Y\n",
    "print (\"H*V*Y = H*H*S*H*S*Y = S*H*S*Y = S*H*X*S = S*Z*H*S = Sdg*H*S =\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=S*H*Sdg #H*V*Z\n",
    "print (\"H*V*Z = H*H*S*H*S*Z = S*H*Sdg =\")\n",
    "display(sympy.Matrix(A.matrix))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*W = H*H*S = S =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABXElEQVQ4EeWUMUvDQBTH/1f7pIamJm5FoQ6Kk9pRBz+BQ4qrg8UvYEFwcPITaEFEnMwmODm5emvFod/AfIMi4iCI8e7iveYgKR0F/0Py/u+Xl7x3OQ5hGKJAIgwDbKbvBQhemsZYKSI6R1Oww0A/yXq5HNo6cXzhsFoi1i0Dbh22BzyXsTtgFIB+e3Hr1FBRUsyEZp1i5n8BR/0JTBYzoeqikjqo741KesE9cFA2wz6wVTZ7JRGPzE6f1voYSwyuu8zG6VxEU/y/3OMc/pO6+mCHRzbBXJvX8xwLQwdWpGW0jHrsMG3IrLXXQ+NNW0dk2Hwb1W8nrw0Z1lLsQ1ur5raKyLBXidlPm9d3uasuxEztSZafqK0Eyt4pUc3XCWiXMdVLw+nFdJ0xLwY5M9R6XEcPmDlTjtVKpH0nNrDYZaCCyO8wW7o5ySN4V8qS6dPJs/ljbLXsbG3Gk87WH5XWb+uKMXPsAAAAAElFTkSuQmCC\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & i\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0⎤\n",
       "⎢    ⎥\n",
       "⎣0  ⅈ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*W*X = S*X = \n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAADUAAAAzBAMAAADFkV1eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGaJdiLNVLurMu++UplCAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABQklEQVQ4EWMQFBRkwAIYBQUFGPT/f8YixcD9//8GBhVsMiAxVsJybOkWKLp5FRH6ZjEINSBJylh+hMuxKjCwbUCSY2BHyHEfYOAC8eAASY7fgIHlF1wCyECSkwfKfcUh15/AwPsdj9w3HHLyCQwsuPQB3cKFyy3cGxhYcfmB9QED8wQc9jFoMchdwCUnVn4WWYpn36fjRMURsiY4m4i4hatFZgwrfcXIPmNIK25ACk81ZDnOBYwaSHLIUgxBDAzZuOT2MDCsF8CRj4AZ0n8BTI6xuADJUEaQXABMjo3lAZIcBzCt3i+AyXWhJCWwXAJMToAfxUygPn+4PpCzkADQvvVwtzDMQZJhYNjNwBAP9wPjLzZkyTgGBku431k+tCLLMS1gfAuXY9gegCzHmF5zASGHLANjD7J0poqrbBXfgK9sBQAk4HMz4HAl4AAAAABJRU5ErkJggg==\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}0 & 1\\\\i & 0\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡0  1⎤\n",
       "⎢    ⎥\n",
       "⎣ⅈ  0⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*W*Y = S*Y =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEIAAAAzBAMAAADRBMO/AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGaJdiLNVLurMu++UplCAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABKklEQVQ4EWMQFBRkwA1Asvr/P+NWwLD//28GFTzyIKlo4lWwpVtgGHZJANmMWQxCDahKGA/PR1bBqsDAtgFVBQNDPbIK7gMMXB/xquA3YGD5hVeFPFDFV7wq+hMYeL8TVPENrwr5BAYW/GYAXcqF36XcGxhY8fuW9QED8wS87mDQYpC7gF+FWPlZdAWn3+sUkBT76AbA+SSkILgedMZINoPdADk0IJkMNTyYEpBVQDIZqgpkeQZoJsOjAprJ8KiAZjIUFeLmyNZAMxmKigQ/ZBXQTIasgmOBJboKYCYDq5BUAgFdRgaUPAXNZMhmoJUP0EyGooLzALIt0EyGokJ+QQKSEmgmQ1HhzxGApAKayVBUcJciK2CAZDIUFSjyMM5QUqFKoAaqJlwDAQCf7lvwhr5RSAAAAABJRU5ErkJggg==\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}0 & 1\\\\- i & 0\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡0   1⎤\n",
       "⎢     ⎥\n",
       "⎣-ⅈ  0⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "H*W*Z = Sdg =\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEIAAAAzBAMAAADRBMO/AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEN2ZRGYyq812u++JIlSvzbOnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABRklEQVQ4EWMQFBRkwA1Asvr/P+NWwLD+/y8GFTzyIKkoIlWwKWIYdGbyBYgY2Axxi4/oKjgeMOoiqWDgxFARxMBwCr+K5QwM7wXASiAuxTQDGAL+D/CpYASpCMCngvcPA0P+BIIqDuBTwQg0wx+vGQxAd7x/gM8MhlUMDPH4fRvNwGABNgIac5jhwfSAcRuSCvbVnyohXDjJeHJ6ApIKuDg2BrHpA5temNioGbCQgNCQ8IBnH1RJBk4DaK5EZB80FUwHoCoQ2QdNBYgLtgWRfXCpQGQfHCqQsg+qCklLqC1I2QdVxQFvZBUHUCVBPN4HoMQMcilS9oEok1ACATVGhp9QFUjZB6ICRvKBihWwbxHZByYHoTkKYCoQ2QdVhfyDA1AzENkHVYU/bwBUBSL7oKrgmgrkQ+IWVQKVN5RUqBKogWYRroEAxcxpgI+1oIEAAAAASUVORK5CYII=\n",
      "text/latex": [
       "$$\\left[\\begin{matrix}1 & 0\\\\0 & - i\\end{matrix}\\right]$$"
      ],
      "text/plain": [
       "⎡1  0 ⎤\n",
       "⎢     ⎥\n",
       "⎣0  -ⅈ⎦"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "print (\"H*W = H*H*S = S =\")\n",
    "A=S #H*W\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A= S*X #H*W*X\n",
    "print (\"H*W*X = S*X = \")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=S*Y #H*W*Y\n",
    "print (\"H*W*Y = S*Y =\")\n",
    "display(sympy.Matrix(A.matrix))\n",
    "A=Sdg #H*W*Z\n",
    "print (\"H*W*Z = Sdg =\")\n",
    "display(sympy.Matrix(A.matrix))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## The Clifford group on 2 qubits\n",
    "\n",
    "The **Pauli group** $P_2$ is generated by the tensor products of the Pauli matrices $\\{A \\otimes B: A,B \\in \\{I,X,Y,Z\\}\\}$. When neglecting the global phase $U(1) \\cong \\mathbb{C}$ we get that $P_2/U(1) \\cong \\mathbb{F}_2^4$. \n",
    "\n",
    "The **Clifford group** $C_2$ on 2-qubits is defined as the normalizer of the Pauli group $P_2$ (when neglecting the global phase $U(1) \\cong \\mathbb{C}$).\n",
    "\n",
    "It turns out that $C_2/P_2 \\cong Sp(4)$, where $Sp(4)$ contains all the symplectic $4 \\times 4$ matrices over the field $\\mathbb{F}_2$, so $Sp(4)$ has 720 elements.\n",
    "\n",
    "According to [4], there are four distinct classes of the 2-qubit Clifford group, and it is proven that this is the optimal decomposition of the 2-qubit Clifford group in terms of the number of CNOT gates."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Recall that the CNOT gate, where qubit 0 is the control and qubit 1 is the target, is:\n",
    "$CX_{0,1} = \\begin{pmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 1 & 0 & 0 \\\\ 0 & 0 & 0 & 1 \\\\ 0 & 0 & 1 & 0 \\end{pmatrix}$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Class 1:**  Consists of $576=24^2$ elements, and represents all 1-qubit Clifford operations.\n",
    "\n",
    "Each element in this class can be written as:\n",
    "$(h_0\\otimes h_1) (v_0\\otimes v_1) (p_0\\otimes p_1)$ where $h_i \\in \\{I,H\\}, v_i \\in \\{I,V,W\\}$ and $p_i \\in \\{I,X,Y,Z\\}$ ,\n",
    "\n",
    "($h_i, v_i, p_i$ operates on the $i$-th qbit)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The size of Class 1 is:  576\n"
     ]
    }
   ],
   "source": [
    "Class1Size = 2*2*3*3*4*4\n",
    "print (\"The size of Class 1 is: \", Class1Size)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Class 2 is called the CNOT-class:** Consists of $5184 = 24^2 \\times 3^2$ elements, \n",
    "and contains the following sequences, which require exactly one CNOT gate.\n",
    "\n",
    "Each element in this class can be written as:\n",
    "$(h_0\\otimes h_1) (v_0\\otimes v_1) CX_{0,1} (v'_0\\otimes v'_1) (p_0\\otimes p_1)$ where $h_i \\in \\{I,H\\}, v_i, v'_i \\in \\{I,V,W\\}, p_i \\in \\{I,X,Y,Z\\}$,\n",
    "and $CX_{0,1}$ is a CNOT-gate, where qubit 0 is the control and qubit 1 is the target."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The size of Class 2 is:  5184\n"
     ]
    }
   ],
   "source": [
    "Class2Size = 2*2*3*3*3*3*4*4\n",
    "print (\"The size of Class 2 is: \", Class2Size)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Class 3 is called the iSWAP-class:** Consists of $5184 = 24^2 \\times 3^2 $ elements, \n",
    "and contains the following sequences, which require two CNOT gates.\n",
    "\n",
    "Each element in this class can be written as:\n",
    "$(h_0\\otimes h_1) (v_0\\otimes v_1) CX_{0,1}CX_{1,0} (v'_0\\otimes v'_1) (p_0\\otimes p_1)$ where $h_i \\in \\{I,H\\}, v_i, v'_i \\in \\{I,V,W\\}, p_i \\in \\{I,X,Y,Z\\}$, and $CX_{0,1}, CX_{1,0}$ are CNOT-gates."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The size of Class 3 is:  5184\n"
     ]
    }
   ],
   "source": [
    "Class3Size = 2*2*3*3*3*3*4*4\n",
    "print (\"The size of Class 3 is: \", Class3Size)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Class 4 is called the SWAP-class:** Consists of $576 = 24^2$ elements, \n",
    "and contains the following sequences, which require three CNOT gates.\n",
    "\n",
    "Each element in this class can be written as:\n",
    "$(h_0\\otimes h_1) (v_0 \\otimes v_1) CX_{0,1} CX_{1,0} CX_{0,1} (p_0\\otimes p_1)$ where $h_i \\in \\{I,H\\}, v_i, \\in \\{I,V,W\\}, p_i \\in \\{I,X,Y,Z\\}$, and $CX_{0,1}, CX_{1,0}$ are CNOT-gates."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The size of Class 4 is:  576\n"
     ]
    }
   ],
   "source": [
    "Class4Size = 2*2*3*3*4*4\n",
    "print (\"The size of Class 4 is: \", Class4Size)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**The size of the Clifford group on 2-qubits**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The size of the 2-qubit Clifford group is:  11520\n"
     ]
    }
   ],
   "source": [
    "TotalSize = Class1Size + Class2Size + Class3Size + Class4Size\n",
    "print (\"The size of the 2-qubit Clifford group is: \", TotalSize)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
